/**
 * @file model_infer_vino.h
 * @brief 基于OpenVINO的YOLO目标检测类
 */

#ifndef MODEL_INFER_VINO_H
#define MODEL_INFER_VINO_H

#pragma once

#include <qglobal.h>

#include <vector>
#include <utility>

#include "common/define.h"
#include "common/common.hpp"

#define NOMINMAX
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif

#include <openvino/openvino.hpp>
#include <opencv2/opencv.hpp>

#include "prep_img_ipp.h"

using namespace ov;
using namespace std;
using namespace cv;
using namespace dnn;

namespace vino_v6 {

    class Yolo_VINO {
    public:
        struct DetRes_VINO {
            int classes;
            float x;
            float y;
            float w;
            float h;
            float prob;
        };

        Yolo_VINO();
        ~Yolo_VINO();

        /**
         * @brief 初始化检测器并加载模型
         */
        bool Init(const char *hdats_path);
        int BatchSize() const;
        
        /**
         * @brief 重置检测器状态并释放资源
         */
        void Reset();

        /**
         * @brief 批量图像目标检测
         */
        void Detect(st_dlm_data *p_imgs,
                    int num,
                    std::vector<std::vector<DetRes_VINO>> &vv_results);

    private:
        std::vector<vector<DetRes_VINO>> postProcess_batch(
            const std::vector<cv::Mat> &img_batch,
            const std::vector<ov::Tensor> &data_tensors,
            float prob_threshold_, float nms_threshold_);

        std::vector<DetRes_VINO> postProcess_yolov6(
            const cv::Mat &src_img, const ov::Tensor &data_tensor,
            float prob_threshold_, float nms_threshold_);

        st_encrypt_info_ovino o_m_info;
        ov::Core core;
        ov::CompiledModel compiled_model;
        std::vector<ov::InferRequest> infer_requests;
        std::vector<void*> m_v_dev_buffer;
        std::vector<int64_t> m_v_dev_buf_size;
        std::vector<std::vector<int>> m_grids;
        std::vector<Tensor> m_v_tensors;
        int CATEGORY = 1;
        int m_out_size = 0;
    };

    float IOUCalculate(
        std::vector<Yolo_VINO::DetRes_VINO>::const_reference det_a,
        std::vector<Yolo_VINO::DetRes_VINO>::const_reference det_b);

    void NmsDetect(
        std::vector<Yolo_VINO::DetRes_VINO> &detections,
        float nms_threshold_);

}

#endif //MODEL_INFER_VINO_H